package com.kehutong.employee.service;

import com.kehutong.common.DoveClient;
import com.kehutong.common.enums.Gender;
import com.kehutong.employee.dao.EmployeeDao;
import com.kehutong.employee.entity.Employee;
import com.kehutong.employee.enums.Identity;
import org.coraframework.authz.Subject;
import org.coraframework.bean.Beans;
import org.coraframework.inject.Inject;
import org.coraframework.json.JSONArray;
import org.coraframework.json.JSONObject;
import org.coraframework.logger.Logger;
import org.coraframework.logger.LoggerFactory;
import org.coraframework.mvc.http.Bean;
import org.coraframework.mvc.http.ReqMapping;
import org.coraframework.mvc.http.result.Result;
import org.coraframework.mvc.util.ReqBody;
import org.coraframework.mvc.util.RequestUtils;
import org.coraframework.mvc.webservice.WebService;
import org.coraframework.orm.Pool;
import org.coraframework.orm.jdbc.JdbcSession;
import org.coraframework.orm.jdbc.Page;
import org.coraframework.orm.jdbc.execute.Condition;
import org.coraframework.orm.jdbc.execute.QueryCondition;
import org.coraframework.orm.jdbc.execute.entity.FindPage;
import org.coraframework.util.EnumUtil;
import org.coraframework.util.Objects;
import org.coraframework.util.UUIDGenerator;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@WebService("/basic/employee/service")
public class EmployeeService  {

	static final Logger logger = LoggerFactory.getLogger(EmployeeService.class);

	@Inject
	private JdbcSession jdbcSession;
	@Inject
	private DoveClient doveClient;
	@Inject
	private EmployeeDao employeeDao;

	@ReqMapping("/list")
	public Object list(JSONObject jsonObject) {
        JSONArray departments = jsonObject.getJSONArray("department");

        FindPage<Employee> find = jdbcSession.findPage(Employee.class)
				.in(jsonObject, "id")
				.like(jsonObject, "name").and();

        if(Objects.nonEmpty(departments)){
            find.markBegin();
            for (Object item: departments) {
                find.like("department",String.valueOf(item)).or();
            }
            find.markEnd().and();
        }
		find.eq("deleted", false);
		Page<Employee> page = find.page(jsonObject).exe();

        return page;
	}

	@ReqMapping("/get")
	public Object get(Employee employee) {
		if (Objects.nonNull(employee) && employee.isDeleted()) {
			return Result.success();
		}
		
		return employee;
	}

	@Bean(newInstance = true, copy = true)
	@ReqMapping("/save")
	public Object save(Employee item, HttpServletRequest req) throws Exception {
		// todo 需要添加验证
		Map<String, Dep> dpmMap = getDepartments(item.getDepartment());
		setProperties(dpmMap, item);


		QueryCondition query = Condition.createQuery(false);
		Map<String,Object> rs = employeeDao.getMaxSort(query);
		item.setSort(Long.valueOf(rs.get("sort").toString()));
		item.setEnable(true);

		Employee employee = jdbcSession.findById(Employee.class, item.getId());
		if(Objects.isNull(employee)){
			jdbcSession.insert(item);
		}else{
            employee.setDeleted(false);
            jdbcSession.updateById(item);
        }

        disposeUser(item, req);

		return Result.success();
	}

	@ReqMapping("/deleteAll")
	public Object deleteAll() {
		List<Employee> list = jdbcSession.findArray(Employee.class).exe();
		jdbcSession.deleteById(list);

		return Result.success();
	}

	@Bean(copy = true)
	@ReqMapping("/update")
	public Object update(Employee item, HttpServletRequest req) throws Exception {
		Map<String, Dep> dpmMap = getDepartments(item.getDepartment());
		
		setProperties(dpmMap, item);
		item.setEnable(true);
        item.setDeleted(false);
		jdbcSession.updateById(item);

        disposeUser(item, req);

		return Result.success();
	}

	private void disposeUser(Employee item, HttpServletRequest req) throws Exception {
        JSONObject user = getUser(item);
        JSONObject emp = getEmployeeMap(item);
        String companyNo = req.getHeader("companyNo");
        String companyName = getCorpName(companyNo);
        if(Objects.isEmpty(user) && Objects.nonEmpty(emp)){
            createUser(item, emp, companyNo, companyName, 0);
        }else if(Objects.nonEmpty(user) && Objects.nonEmpty(emp)){
			changeUser(item, emp, user);
        }
    }

	@ReqMapping("/delete")
	public Object delete(Employee item) throws Exception {
		item.setDeleted(true);
		jdbcSession.updateById(item);

		// 刪除员工后删除员工账号信息
		JSONObject user = getUser(item);
		if(Objects.nonNull(user)){
			cancelUser(item);
		}

		return Result.success();
	}

	@ReqMapping("/updateDutyDepartment")
	public Object updateDutyDepartment(JSONObject json) throws Exception {

		List<Employee> oldEmployees = jdbcSession.findArray(Employee.class)
				.in("id", json.getJSONArray("oldIds"))
				.exe();

		//删除旧的主管的部门
		for (Employee item: oldEmployees) {
			List<String> dutyDepartment = item.getDutyDepartment();
			dutyDepartment.remove(json.getString("department"));
			item.setDutyDepartment(dutyDepartment);


			Map<String, Dep> dpmMap = getDepartments(dutyDepartment);
			List<String> dutyDepartmentName = new ArrayList<>();
			dutyDepartment.forEach(id ->{
				dutyDepartmentName.add(dpmMap.get(id).getName());
			});
			item.setDutyDepartmentName(dutyDepartmentName);

			if(Objects.isEmpty(item.getDutyDepartment())){
				item.setIdentity(Identity.EMPLOYEE);
			}
		}
		jdbcSession.updateById(oldEmployees);


		List<Employee> employees = jdbcSession.findArray(Employee.class)
				.in("id", json.getJSONArray("ids"))
				.exe();
		employees.forEach(item -> {
			Set<String> dutyDepartment = new HashSet<>(item.getDutyDepartment());
			dutyDepartment.add(json.getString("department"));
			item.setDutyDepartment(new ArrayList<>(dutyDepartment));

			Set<String> dutyDepartmentName = new HashSet<>(item.getDutyDepartmentName());
			dutyDepartmentName.add(json.getString("departmentName"));
			item.setDutyDepartmentName(new ArrayList<>(dutyDepartmentName));

			item.setIdentity(Identity.LEAD);
		});

		jdbcSession.updateById(employees);

		return Result.success();
	}
	
	@ReqMapping("/saveBatch")
	public Object saveBatch(JSONObject json) throws Exception {
		Map<String, Dep> dpmMap = getDepartments(Collections.emptyList());
		JSONArray userList = json.getJSONArray("userList");

		List<String> userIds = new ArrayList<>(userList.size());
		for (int i = 0; i < userList.size(); i ++) {
			userIds.add(userList.getJSONObject(i).getString("id"));
		}

		Map<String, JSONObject> userMap = getUserMap(userIds);
		Map<String, JSONObject> employeeMap = getEmployeeMap(userIds);

		for (int i = 0; i < userList.size(); i ++) {
			JSONObject jsonObject = userList.getJSONObject(i);
			
			String id = jsonObject.getString("id");
			String gender = jsonObject.getString("gender");
			String identity = jsonObject.getString("identity");
			String qrCode = jsonObject.getString("qrCode");
			String avatar = jsonObject.getString("avatar");
			Gender genderObj= EnumUtil.getEnum(Gender.class, gender);
			Identity identityObj= EnumUtil.getEnum(Identity.class, identity);


			Employee employee = jdbcSession.findById(Employee.class, id);
			if (Objects.isNull(employee)) {
				employee = Pool.newInstance(Employee.class, id);
				Beans.from(jsonObject).to(employee).exclude("id").igornNull().copy();
				setProperties(dpmMap, employee);
				employee.setGender(genderObj);
				employee.setIdentity(identityObj);
				employee.setQrCode(qrCode);

				QueryCondition query = Condition.createQuery(false);
				Map<String,Object> rs = employeeDao.getMaxSort(query);
				employee.setSort(Long.valueOf(rs.get("sort").toString()));
				employee.setQrCode(qrCode);
				employee.setEnable(true);
                employee.setAvatar(avatar);
				jdbcSession.insert(employee);
			} else {
				boolean enable = employee.isEnable();
				Beans.from(jsonObject).to(employee).exclude("id").igornNull().copy();
				setProperties(dpmMap, employee);
				employee.setEnable(enable);
				employee.setGender(genderObj);
				employee.setIdentity(identityObj);
				employee.setEnable(true);
                employee.setAvatar(avatar);
				jdbcSession.updateById(employee);
			}

			// 创建员工账号
			JSONObject user = userMap.get(id);
			JSONObject emp = employeeMap.get(id);
			String companyNo = json.getString("companyNo");
			int authMode = json.getIntValue("authMode");
			String companyName = getCorpName(companyNo);
			if(Objects.isEmpty(user) && Objects.nonEmpty(emp)){
				createUser(employee, emp, companyNo, companyName, authMode);
			}else if(Objects.nonEmpty(user) && Objects.nonEmpty(emp)){
				changeUser(employee, emp , user);
			}
		}
		saveDepartments(dpmMap.values());
		return Result.success();
	}

	@ReqMapping(value="/saveInnerBatch", reqBody = ReqBody.TEXT)
	public Object saveInnerBatch(HttpServletRequest req) throws Exception {
		String text = RequestUtils.readText(req);
		JSONObject json = JSONObject.parseObject(text);
		Map<String, Dep> dpmMap = getDepartments(Collections.emptyList());
		JSONArray userList = json.getJSONArray("userList");
		List<String> userIds = new ArrayList<>(userList.size());
		for (int i = 0; i < userList.size(); i ++) {
			userIds.add(userList.getJSONObject(i).getString("id"));
		}

		Map<String, JSONObject> userMap = getUserMap(userIds);
		Map<String, JSONObject> employeeMap = getInnerEmployeeMap(userIds);

		for (int i = 0; i < userList.size(); i ++) {
			JSONObject jsonObject = userList.getJSONObject(i);

			String id = jsonObject.getString("id");
			String gender = jsonObject.getString("gender");
			String identity = jsonObject.getString("identity");
			String qrCode = jsonObject.getString("qrCode");
			String avatar = jsonObject.getString("avatar");
			Gender genderObj= EnumUtil.getEnum(Gender.class, gender);
			Identity identityObj= EnumUtil.getEnum(Identity.class, identity);


			Employee employee = jdbcSession.findById(Employee.class, id);
			if (Objects.isNull(employee)) {
				employee = Pool.newInstance(Employee.class, id);
				Beans.from(jsonObject).to(employee).exclude("id").igornNull().copy();
				setProperties(dpmMap, employee);
				employee.setGender(genderObj);
				employee.setIdentity(identityObj);
				employee.setQrCode(qrCode);

				QueryCondition query = Condition.createQuery(false);
				Map<String,Object> rs = employeeDao.getMaxSort(query);
				employee.setSort(Long.valueOf(rs.get("sort").toString()));
				employee.setQrCode(qrCode);
				employee.setEnable(true);
				employee.setAvatar(avatar);
				jdbcSession.insert(employee);
			} else {
				boolean enable = employee.isEnable();
				Beans.from(jsonObject).to(employee).exclude("id").igornNull().copy();
				setProperties(dpmMap, employee);
				employee.setEnable(enable);
				employee.setGender(genderObj);
				employee.setIdentity(identityObj);
				employee.setEnable(true);
				employee.setAvatar(avatar);
				jdbcSession.updateById(employee);
			}

			// 创建员工账号
			JSONObject user = userMap.get(id);
			JSONObject emp = employeeMap.get(id);
			String companyNo = json.getString("companyNo");
			int authMode = json.getIntValue("authMode");
			String companyName = getCorpName(companyNo);
			if(Objects.isEmpty(user) && Objects.nonEmpty(emp)){
				createUser(employee, emp, companyNo, companyName, authMode);
			}else if(Objects.nonEmpty(user) && Objects.nonEmpty(emp)){
				changeUser(employee, emp , user);
			}
		}
		saveDepartments(dpmMap.values());
		return Result.success();
	}

	/**
	 * 第三方公司的员工同步
	 *
	 * @author zhouweipeng
	 * @param json
	 * @return
	 * @throws Exception
	 */
	@ReqMapping("/saveThridBatch")
	public Object saveThridBatch(JSONObject json) throws Exception {
		JSONArray userList=json.getJSONArray("userList");
		JSONArray backJsonArray=new JSONArray();
		for(int i=0,len=userList.size();i<len;i++){
			JSONObject user=userList.getJSONObject(i);
			String khtId=user.getString("khtId");
			String guid=user.getString("guid");
			String fullName=user.getString("fullName"); //真实姓名
			String email=user.getString("email"); //email
			String gender=user.getString("gender"); //性别
			String mobile=user.getString("mobile"); //电话
			String seq=user.getString("seq"); //排序
			String disabledStatus=user.getString("disabledStatus");//状态（-1、删除(上游系统删除)，0、禁用，1、启用）
			String deleteStatus=user.getString("deleteStatus"); //删除状态（0、删除(中台删除)，1、未删除）
			String phoneticAlphabet=user.getString("phoneticAlphabet");//姓名全拼
			String khtOrgGuid=user.getString("khtOrgGuid");//机构编码
			boolean deleted="0".equals(deleteStatus)?true:false;
			boolean enable="0".equals(disabledStatus)?false:true;
			Employee employee=null;
			Boolean insert=true;
			//建立双方关系返回
			JSONObject middleRelationJson=new JSONObject();
			if(Objects.nonEmpty(khtId)){
				employee=Pool.get(Employee.class,khtId);
				insert=false;
			}else{
				employee=Pool.newInstance(Employee.class);
				middleRelationJson.put("thirdId",guid); //第三方id
				middleRelationJson.put("khtId",employee.getId()); //客户通id
				backJsonArray.add(middleRelationJson);
			}
			if(khtOrgGuid!=null){
				List<String>departmentList=new ArrayList<String>();
				departmentList.add(khtOrgGuid);
				Map<String,Dep>departmentMap=getDepartments(departmentList);
				List<String>departmentNameList=new ArrayList<String>();
				departmentNameList.add(departmentMap.get(khtOrgGuid).getName());
				employee.setDepartment(departmentList);
				employee.setDepartmentName(departmentNameList);
			}
			employee.setMobile(mobile);
			employee.setGender(Gender.getGenderById(gender));
			employee.setThirdName(fullName);
			employee.setName(phoneticAlphabet);
			employee.setEmail(email);
			if(seq!=null){
				employee.setSort(Long.valueOf(seq));
			}else{
				employee.setSort(0);
			}
			employee.setAlias("中海地产");
			employee.setDeleted(deleted);
			employee.setEnable(enable);
			if(insert){
				jdbcSession.insert(employee);
			}else{
				jdbcSession.updateById(employee);
			}
		}
		return backJsonArray;
	}

	/**
	 * 获取内建模式腾讯员工映射关系信息
	 * @param ids
	 * @return
	 * @throws Exception
	 */
	public Map<String, JSONObject> getInnerEmployeeMap(List<String> ids) throws Exception{
		JSONObject result = doveClient.post("/wwin/event/change_contact/getEmployeeByKhtIds",(http)->{
			JSONObject body = new JSONObject();
			body.put("khtIds", ids);
			http.setBody(body.toJSONString());
		});

		Map<String,JSONObject> employeeMap = new HashMap<>();
		if (result.getIntValue("code") == 200) {
			JSONArray data = result.getJSONArray("data");
			data.forEach(item->{
				JSONObject obj = (JSONObject) item;
				employeeMap.put(obj.getString("khtid"), obj);
			});
		}

		return employeeMap;
	}
	public Map<String, JSONObject> getEmployeeMap(List<String> ids) throws Exception{
		JSONObject result = doveClient.post("/kht-bin/wwout/getEmployeeByKhtIds",(http)->{
			JSONObject body = new JSONObject();
			body.put("khtIds", ids);
			http.setBody(body.toJSONString());
		});

		Map<String,JSONObject> employeeMap = new HashMap<>();
		if (result.getIntValue("code") == 200) {
			JSONArray data = result.getJSONArray("data");
			data.forEach(item->{
				JSONObject obj = (JSONObject) item;
				employeeMap.put(obj.getString("khtid"), obj);
			});
		}

		return employeeMap;
	}

	private JSONObject getEmployeeMap(Employee employee) throws Exception {
		JSONObject result = doveClient.post("/kht-bin/wwout/getEmployeeByKhtId",(http)->{
			JSONObject body = new JSONObject();
			body.put("khtId", employee.getId());
			http.setBody(body.toJSONString());
		});

		if (result.getIntValue("code") == 200) {
			return result.getJSONObject("data");
		}

		return null;
	}

	private JSONObject getUser(Employee employee) throws Exception {
		JSONObject rs = doveClient.post("/kht-bin/auth/user/get_user", http-> {
			http.addParam("id", employee.getId());
		});

		logger.info("-----------------------------------------/kht-bin/auth/user/get_user[rs]:{}", rs);
		if (rs.getIntValue("code") == 200) {
			return rs.getJSONObject("data");
		}

		return null;
	}

	private Map<String, JSONObject> getUserMap(List<String> ids) throws Exception {
		JSONObject rs = doveClient.post("/kht-bin/auth/user/list", http-> {
			JSONObject body = new JSONObject();
			body.put("id", ids);
			http.setBody(body.toJSONString());
		});

		Map<String,JSONObject> userMap = new HashMap<>();
		if (rs.getIntValue("code") == 200) {
			JSONArray data = rs.getJSONArray("data");

			data.forEach(item->{
				JSONObject obj = (JSONObject) item;
				userMap.put(obj.getString("id"), obj);
			});
		}

		return userMap;
	}

	private void createUser(Employee employee, JSONObject employeeMap, String companyNo, String companyName, int authMode) throws Exception {
		doveClient.post("/kht-bin/auth/user/create_user", http-> {
			http.addParam("id",  employee.getId());
			http.addParam("login_name", companyNo + "_" + employeeMap.getString("userId"));
			http.addParam("name", employeeMap.getString("name"));
			http.addParam("avatar", employee.getAvatar());
			http.addParam("gender", Objects.nonNull(employee.getGender()) ? employee.getGender().getId() : "");
			http.addParam("userId", employeeMap.getString("userId"));
			http.addParam("corpNo", companyNo);
			http.addParam("corpName", companyName);
			http.addParam("password", Subject.encrypt("kehutong@2020"));
			if (authMode == 0) {
				http.addParam("roles", "4");
			} else {
				http.addParam("roles", "5");
			}
		});
	}

    private void changeUser(Employee employee, JSONObject employeeMap, JSONObject user) throws Exception {
        doveClient.post("/kht-bin/auth/user/change_user", http-> {
        	JSONObject body = new JSONObject();
        	body.put("id", employee.getId());
            String avatar = user.getString("avatar");
            if(Objects.isEmpty(avatar)){
				body.put("avatar", employee.getAvatar());
			}
            JSONObject gender = user.getJSONObject("gender");
            if(Objects.isEmpty(gender)){
				body.put("gender", Objects.nonNull(employee.getGender()) ? employee.getGender().getId() : "");
			}
			String userId = user.getString("userId");
			if(Objects.isEmpty(userId)){
				body.put("userId", employeeMap.getString("userId"));
			}
			body.put("name", employee.getName());
			http.setBody(body.toJSONString());
        });
    }

	private void cancelUser(Employee employee) throws Exception {
		doveClient.post("/kht-bin/auth/user/cancel_user", http-> {
			http.addParam("id",  employee.getId());
		});
	}

	private String getCorpName(String companyNo) throws Exception {
		JSONObject result = doveClient.post("/admin/service/corp/get", http -> {
			http.addParam("id", companyNo);
		});
		int code = result.getIntValue("code");
		if (code == 200) {
			return result.getJSONObject("data").getString("name");
		}
		return null;
	}
	
	private void setProperties(Map<String, Dep> dpmMap, Employee employee) {
		List<String> buf = new ArrayList<>(4);
		for (String depNo : employee.getDepartment()) {
			Dep dep = dpmMap.get(depNo);
			if(Objects.nonNull(dep)){
				buf.add(dep.getName());
				dep.addCount(1);
			}
		}
		employee.setDepartmentName(buf);
		
		List<String> buf1 = new ArrayList<>(4);
		for (String depNo : employee.getDutyDepartment()) {
			Dep dep = dpmMap.get(depNo);
			if(Objects.nonNull(dep)){
				buf1.add(dep.getName());
				dep.adLeader(employee);
			}
		}
		employee.setDutyDepartmentName(buf1);
	}
	
	private Map<String, Dep> getDepartments(List<String> departments) throws Exception {
		JSONObject jsonObject = doveClient.post("/basic/department/service/listAll", http->{
			http.addParam("departments", String.join(",", departments));
		});
		
		JSONArray array = jsonObject.getJSONArray("data");
		Map<String, Dep> deparmentMap = new HashMap<>(array.size());
		for (int i = 0; i < array.size(); i ++) {
			Dep dep = new Dep(array.getJSONObject(i));
			deparmentMap.put(dep.getId(), dep);
		}
		return deparmentMap;
	}
	
	private void saveDepartments(Collection<Dep> departments) throws Exception {
		doveClient.post("/basic/department/service/saveDepartment", http->{
			JSONObject json = new JSONObject();
			json.put("data", new ArrayList<>(departments));
			http.setBody(json.toJSONString());
		});
	}

	/**
	 * 内建模式本地新增完成后更新员工主键
	 * @param json
	 * @return
	 * @throws Exception
	 */
	@Bean(copy = true)
	@ReqMapping("/updateIdByInner")
	public Object updateIdByInner(JSONObject json) throws Exception {
		String oldId = json.getString("oldId");
		String newId = json.getString("newId");
		Employee item = Pool.get(Employee.class,oldId);
		item.setId(newId);
		jdbcSession.updateById(item,oldId);
		return Result.success();
	}
	
	
}
